/**
 * map封装，互斥锁方式
 * map_type指定容器类型，std::map, std::unordered_map，或boost::unordered_map等。
 * key_type 键类型
 * value_type 值类型
 * 
 * 开发者   : Marco
 * 创建时间 : 2016年7月29日, 下午10:54
 */

#ifndef __MARCOPP_CONTAINER_MAP_MUTEX_HPP__
#define __MARCOPP_CONTAINER_MAP_MUTEX_HPP__

#include "container.h"
#include <pthread.h>
#include <utility>

MARCOPP_NAMESPACE_BEGIN
MARCOPP_NAMESPACE_CONTAINER_BEGIN

template <typename map_type, typename key_type, typename value_type> class map_mutex {
public:
    typedef typename map_type::const_iterator const_iterator;
    typedef typename map_type::iterator iterator;
    typedef typename std::pair<iterator, bool> ins_pair; // 插入结果
    
    explicit map_mutex(void) : mutex(PTHREAD_MUTEX_INITIALIZER) { }
    
    /**
     * 指定哈希桶初始大小，适用于unordered_map
     * @param size 大小
     */
    explicit map_mutex(int size) : mutex(PTHREAD_MUTEX_INITIALIZER) { m_.rehash(size); }
    
    /**
     * 插入节点相关
     */
    void insert(const key_type& key, const value_type& value) { // 插入
	pthread_mutex_lock(&mutex);
	m_.insert(typename map_type::value_type(key, value));
	pthread_mutex_unlock(&mutex);
    }
    bool insert_bool(const key_type& key, const value_type& value) { // 插入并获取是否成功
	bool ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(key, value)).second;
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    ins_pair insert_res(const key_type& key, const value_type& value) { // 插入并获取结果
	ins_pair ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(key, value));
	pthread_mutex_unlock(&mutex);
	return ret;
    }
   
#if (__cplusplus >= 201103L)
    // key为右值引用
    void insert(key_type&& key, const value_type& value) { // 插入
	pthread_mutex_lock(&mutex);
	m_.insert(typename map_type::value_type(std::forward<key_type>(key), value));
	pthread_mutex_unlock(&mutex);
    }
    bool insert_bool(key_type&& key, const value_type& value) { // 插入并获取是否成功
	bool ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(std::forward<key_type>(key), value)).second;
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    ins_pair insert_res(key_type&& key, const value_type& value) { // 插入并获取结果
	ins_pair ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(std::forward<key_type>(key), value));
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    
    // value为右值引用
    void insert(const key_type& key, value_type&& value) { // 插入
	pthread_mutex_lock(&mutex);
	m_.insert(typename map_type::value_type(key, std::forward<value_type>(value)));
	pthread_mutex_unlock(&mutex);
    }
    bool insert_bool(const key_type& key, value_type&& value) { // 插入并获取是否成功
	bool ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(key, std::forward<value_type>(value))).second;
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    ins_pair insert_res(const key_type& key, value_type&& value) { // 插入并获取结果
	ins_pair ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(key, std::forward<value_type>(value)));
	pthread_mutex_unlock(&mutex);
	return ret;
    }
  
    // key,value均为右值引用
    void insert(key_type&& key, value_type&& value) { // 插入
	pthread_mutex_lock(&mutex);
	m_.insert(typename map_type::value_type(std::forward<key_type>(key), std::forward<value_type>(value)));
	pthread_mutex_unlock(&mutex);
    }
    bool insert_bool(key_type&& key, value_type&& value) { // 插入并获取是否成功
	bool ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(std::forward<key_type>(key), std::forward<value_type>(value))).second;
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    ins_pair insert_res(key_type&& key, value_type&& value) { // 插入并获取结果
	ins_pair ret;
	pthread_mutex_lock(&mutex);
	ret = m_.insert(typename map_type::value_type(std::forward<key_type>(key), std::forward<value_type>(value)));
	pthread_mutex_unlock(&mutex);
	return ret;
    }
#endif // (__cplusplus >= 201103L)
    
    /**
     * 删除指定的key
     * @param key 键
     * @return 删除成功或失败
     */
    bool erase(const key_type& key) {
	bool ret;
	pthread_mutex_lock(&mutex);
	ret = (m_.erase(key) == 1);
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    
    /**
     * 根据迭代器删除
     * @param it 迭代器对象
     * @return 被删除的下一个迭代器对象
     */
    typename map_type::iterator erase(const typename map_type::iterator& it) {
	typename map_type::iterator nextit;
	pthread_mutex_lock(&mutex);
	nextit = m_.erase(it);
	pthread_mutex_unlock(&mutex);
	return nextit;
    }

#if (__cplusplus >= 201103L)
    /**
     * 删除指定的key
     * @param key 键, 右值方式
     * @return 删除成功或失败
     */
    bool erase(key_type&& key) {
	bool ret;
	pthread_mutex_lock(&mutex);
	ret = (m_.erase(std::forward<key_type>(key)) == 1);
	pthread_mutex_unlock(&mutex);
	return ret;
    }
#endif // (__cplusplus >= 201103L)

    /**
     * 根据key查找值
     * @param key 键
     * @param value (out)值, 如果查找成功，value类型需要支持赋值运算, 查找失败则不对value做任何改动
     * @return 成功或失败
     */
    bool find(const key_type& key, value_type& value) {
	bool ret = false;
	typename map_type::iterator it;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(key)) != m_.end()) {
	    value = (*it).second;
	    ret = true;
	}
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    
    /**
     * 直接返回值，仅适用于value是指针的类型
     * @param key 键
     * @return 值
     */
    value_type find(const key_type& key) {
	typename map_type::iterator it;
	value_type tmp = NULL;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(key)) != m_.end()) {
	    tmp = (*it).second;
	}
	pthread_mutex_unlock(&mutex);
	return tmp;
    }
    
    bool find_res(const key_type& key, typename map_type::iterator& it) {
	bool ret = false;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(key)) != m_.end())
	    ret = true;
	pthread_mutex_unlock(&mutex);
	return ret;
    }

#if (__cplusplus >= 201103L)
    /**
     * 根据key查找值
     * @param key 键，右值引用型
     * @param value (out)值, 如果查找成功，value类型需要支持赋值运算, 查找失败则不对value做任何改动
     * @return 成功或失败
     */
    bool find(key_type&& key, value_type& value) {
	bool ret = false;
	typename map_type::iterator it;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(std::forward<key_type>(key))) != m_.end()) {
	    value = (*it).second;
	    ret = true;
	}
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    
    /**
     * 直接返回值，适用于value是指针的类型
     * @param key 键，右值引用
     * @return 值
     */
    value_type find(key_type&& key) {
	typename map_type::iterator it;
	value_type tmp = NULL;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(std::forward<key_type>(key))) != m_.end()) {
	    tmp = (*it).second;
	}
	pthread_mutex_unlock(&mutex);
	return tmp;
    }
    
    bool find_res(const key_type& key, typename map_type::iterator& it) {
	bool ret = false;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(std::forward<key_type>(key))) != m_.end())
	    ret = true;
	pthread_mutex_unlock(&mutex);
	return ret;
    }
#endif // __cplusplus >= 201103L
    
    /**
     * 查找并从map中删除, 会将已从map中删除的赋值到value
     * @param key 键
     * @param value(out)值, 如果查找成功
     * @return 成功或失败
     */
    bool find_and_erase(const key_type& key, value_type& value) {
	typename map_type::iterator it;
	bool ret = false;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(key)) != m_.end()) {
	    value = (*it).second;
	    m_.erase(it);
	    ret = true;
	}
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    
    /**
     * 查找并从map中删除, 适合value是指针类型
     * @param key 键
     * @return value值或NULL失败
     */
    value_type find_and_erase(const key_type& key) {
	typename map_type::iterator it;
	value_type value = NULL;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(key)) != m_.end()) {
	    value = (*it).second;
	    m_.erase(it);
	}
	pthread_mutex_unlock(&mutex);
	return value;
    }
    
#if (__cplusplus >= 201103L)    
    /**
     * 查找并从map中删除, 会将已从map中删除的赋值到value
     * @param key 键, 右值方式
     * @param value(out)值, 如果查找成功
     * @return 成功或失败
     */
    bool find_and_erase(key_type&& key, value_type& value) {
	typename map_type::iterator it;
	bool ret = false;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(std::forward<key_type>(key))) != m_.end()) {
	    value = (*it).second;
	    m_.erase(it);
	    ret = true;
	}
	pthread_mutex_unlock(&mutex);
	return ret;
    }
    
    /**
     * 查找并从map中删除, 适合value是指针类型
     * @param key 键, 右值方式
     * @return value值或NULL失败
     */
    value_type find_and_erase(key_type&& key) {
	typename map_type::iterator it;
	value_type value = NULL;
	pthread_mutex_lock(&mutex);
	if ((it = m_.find(std::forward<key_type>(key))) != m_.end()) {
	    value = (*it).second;
	    m_.erase(it);
	}
	pthread_mutex_unlock(&mutex);
	return value;
    }
 #endif // __cplusplus >= 201103L
    
    const_iterator begin(void) const { return m_.begin(); }
    iterator begin(void) { return m_.begin(); }
    const_iterator end(void) const { return m_.end(); }
    iterator end(void) { return m_.end(); }
    void rehash(int size) { m_.rehash(size); }
    int size(void) { return (int)m_.size(); }
    
    void lock(void) { pthread_mutex_lock(&mutex); }
    void unlock(void) { pthread_mutex_unlock(&mutex); }
    
private:
    map_type m_;    
    pthread_mutex_t mutex;
}; // class map_mutex

MARCOPP_NAMESPACE_CONTAINER_END
MARCOPP_NAMESPACE_END
#endif /* __MARCOPP_CONTAINER_MAP_MUTEX_HPP__ */